﻿#region Imports

using System.Collections.Generic;
using NHibernate;
using Spring.Data.NHibernate;
using Spring.Data.NHibernate.Generic.Support;
using d3PrtDgn.Core.BaseData;
using d3PrtDgn.Data.IDAO;
using d3PrtDgn.Data.Domain.Entity;

#endregion

namespace d3PrtDgn.Data.DAO
{
	/// <summary>
	/// Hibernate Album DAO
	/// </summary>
	class AlbumDao : BaseDao, IAlbumDao
	{

		#region IAlbumDao members

		/// <summary>
		/// Saves or updates album
		/// </summary>
		/// <param name="album"></param>
		/// <returns></returns>
		public Album SaveOrUpdate(Album album)
		{
            return base.SaveOrUpdate(album) as Album;
		}

		/// <summary>
		/// Loads all albums
		/// </summary>
		/// <returns></returns>
		public IList<Album> FindAll()
		{
            return base.FindAll() as IList<Album>;
		}

		/// <summary>
		/// Loads all users albums
		/// </summary>
		/// <param name="owner"></param>
		/// <returns></returns>
		public IList<Album> FindAllForOwner(User owner)
		{
			return HibernateTemplate.Find<Album>("from Album a where a.Owner = ?", owner);
		}

		/// <summary>
		/// Loads one album with specified id owned by specified owner
		/// </summary>
		/// <param name="id"></param>
		/// <param name="owner"></param>
		/// <returns></returns>
		public Album FindById(int id, User owner)
		{
			if (owner == null)
				return HibernateTemplate.Load<Album>(id);
			else
			{
				IList<Album> albums = HibernateTemplate.Find<Album>("from Album a where a.Id = ? and a.Owner.Id = ?", new object[] {id,  owner.Id});

				if (albums.Count > 0)
					return albums[0];
			}

			return null;
		}

		/// <summary>
		/// Loads album acoording to abbreviation,
		/// checks owner on private album if supplied
		/// </summary>
		/// <param name="abbrev">Album abbreviation</param>
		/// <param name="owner">Album owner</param>
		/// <returns></returns>
		public Album FindByAbbreviation(string abbrev, User owner)
		{
			IList<Album> albums;

			if (owner != null)
			{
				albums =
					HibernateTemplate.Find<Album>("from Album a where a.Abbreviation = ? and (a.Owner.Id = ? or a.Visibility = ?)",
					                              new object[] {abbrev, owner.Id, Visibility.Public});
			}
			else
			{
				albums = HibernateTemplate.Find<Album>("from Album a where a.Abbreviation = ?", abbrev);
			}

			if(albums.Count > 0)
			{
				return albums[0];
			}

			return null;
		}

		/// <summary>
		/// Deletes album
		/// </summary>
		/// <param name="album"></param>
		public void Delete(Album album)
		{
            base.Delete(album);
		}

		/// <summary>
		/// Finds public albums in desired category
		/// </summary>
		/// <returns></returns>
		public IList<Album> FindAllPublic()
		{
			return HibernateTemplate.Find<Album>("from Album a where a.Visibility = ?", Visibility.Public);
		}

		/// <summary>
		/// Finds public albums in desired category
		/// </summary>
		/// <param name="category"></param>
		/// <returns></returns>
		public IList<Album> FindPublicByCategory(Category category)
		{
			return HibernateTemplate.Find<Album>("from Album a where a.Category = ? and a.Visibility = ?", new object[] {category, Visibility.Public});
		}

		/// <summary>
		/// Finds all albums in desired category for current user
		/// </summary>
		/// <param name="category"></param>
		/// <param name="user"></param>
		/// <returns></returns>
		public IList<Album> FindAllByCategory(Category category, User user)
		{
			if(user == null || user.Id == 0)
			{
				return FindPublicByCategory(category);
			}

			return
				HibernateTemplate.Find<Album>(
					"from Album a where a.Category = ? and (a.Visibility = ? or (a.Visibility = ? and a.Owner = ?))",
					new object[] {category, Visibility.Public, Visibility.Private, user});
		}

		/// <summary>
		/// Loads all albums visible for user
		/// </summary>
		/// <param name="user"></param>
		/// <returns></returns>
		public IList<Album> FindAllVisible(User user)
		{
			return
				HibernateTemplate.Find<Album>(
					"from Album a where (a.Visibility = ? or (a.Visibility = ? and a.Owner = ?))",
					new object[] {Visibility.Public, Visibility.Private, user});
		}

		/// <summary>
		/// Checks if album abbreviation is unique
		/// </summary>
		/// <param name="abbreviation">Abbreviation to check</param>
		/// <param name="id">ID of album to ignore</param>
		/// <returns>Flag if abbreviation is unique</returns>
		public bool IsUnique(string abbreviation, int id)
		{
			return HibernateTemplate.Find<Album>("from Album a where a.Abbreviation = ? and a.Id != ?",
			                                     new object[] {abbreviation, id}).Count == 0;
		}

		#endregion
	}
}
